package cn.tedu.charging.order.service;

import cn.tedu.charging.common.constant.ChargingTopicConstants;
import cn.tedu.charging.common.enums.GunStatusEnum;
import cn.tedu.charging.common.message.CheckResultMsg;
import cn.tedu.charging.common.message.DelayMsg;
import cn.tedu.charging.common.message.StartChargingCommand;
import cn.tedu.charging.common.pojo.param.GunStatusUpdateParam;
import cn.tedu.charging.common.pojo.param.OrderAddParam;
import cn.tedu.charging.common.protocol.JsonResult;
import cn.tedu.charging.common.utils.CronUtil;
import cn.tedu.charging.common.utils.XxlJobTaskUtil;
import cn.tedu.charging.order.feign.DeviceClient;
import cn.tedu.charging.order.feign.UserClient;
import cn.tedu.charging.order.producer.OrderEmqxProducer;
import cn.tedu.charging.order.producer.RabbitProducer;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Random;

@Service
@Slf4j
public class OrderService {
    @Autowired
    private DeviceClient deviceClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private OrderEmqxProducer producer;
    @Autowired
    private RabbitProducer rabbitProducer;
    @Autowired
    private RestTemplate restTemplate;
    public String createOrder(OrderAddParam param) {
        //1.生成订单编号 只需要创建一个唯一值
        log.info("创建订单-正在生成订单编号");
        String orderNo=generateOrderNo();
        log.info("创建订单-完成生成订单编号:{}",orderNo);
        //2.更新充电枪状态 从空闲 更新到使用中
        log.info("创建订单-更新枪状态,枪id:{}",param.getGunId());
        Boolean success=updateGunStatus(param.getGunId(), GunStatusEnum.USING);
        log.info("创建订单-更新枪状态,枪id:{},更新结果:{}",param.getGunId(),success);
        //3.获取用户信息 车辆id
        log.info("创建订单-获取车辆id,用户id:{}",param.getUserId());
        //Integer carId=getCarInfo(param.getUserId());
        log.info("创建订单-获取车辆id,用户id:{},车辆id:{}",param.getUserId(),1);
        //4.发送开始充电命令让设备自检充电
        //指令消息中的参数 orderNo gunId pileId message
        startCharging(orderNo,param,"设备正在准备充电");
        Integer delayTime=50000;
        //5.延迟1分钟任务
        String cronExpression = CronUtil.delayCron(delayTime);
        boolean jobTask = XxlJobTaskUtil.createJobTask(restTemplate, cronExpression, 5, orderNo);
        if (!jobTask){
            log.debug("创建自检任务失败");
        }
        //5.发送延迟消息 兜底自检无响应
        rabbitProducer.send(new DelayMsg(orderNo,param.getUserId(), param.getGunId()));
        return orderNo;
    }

    private void startCharging(String orderNo, OrderAddParam param, String message) {
        //调用producer发送消息 需要String message String topic
        StartChargingCommand command=
                new StartChargingCommand(orderNo,param.getGunId(),param.getPileId(),message);
        //将command转化成json字符串
        String msg = JSON.toJSONString(command);
        //准备主题
        String topic= ChargingTopicConstants.START_CHARGING_TOPIC_PREFIX+param.getPileId();
        log.info("订单发送开始充电指令到topic:{},命令消息:{}",topic,msg);
        boolean success = producer.sendMessage(topic, msg);
        log.info("订单发送开始充电指令到topic:{},命令消息:{},发送结果:{}",topic,msg,success);
    }

    private Integer getCarInfo(Integer userId) {
        JsonResult<Integer> userCarInfo = userClient.getUserCarInfo(userId);
        return userCarInfo.getData();
    }

    private Boolean updateGunStatus(Integer gunId, GunStatusEnum gunStatusEnum) {
        GunStatusUpdateParam param=new GunStatusUpdateParam();
        param.setGunId(gunId);
        param.setStatus(gunStatusEnum.getStatus());
        JsonResult<Boolean> result = deviceClient.updateGunStatus(param);
        //如果返回的结果是false,整个扫码流程就结束了.
        //TODO 通知手机端用户 webSocket
        return result.getData();
    }

    private String generateOrderNo() {
        //一般订单编号生成需要递增趋势 可以使用当前系统时间 为了避免同一个毫秒 出现相同订单 每个订单+随机数
        String orderNo="";
        //先来一个时间戳
        long now=System.currentTimeMillis();
        //后面拼接一个6为随机数字
        int randCode=new Random().nextInt(900000)+100000;
        orderNo=now+""+randCode;
        return orderNo;
    }

    public void receiveCheckResult(CheckResultMsg checkResultMsg) {

    }
}
